package com.autoglm.android.core

import android.util.Log
import com.autoglm.android.core.db.AppKnowledgeBase
import com.autoglm.android.core.llm.LLMService
import com.autoglm.android.core.models.AppInfo
import com.autoglm.android.core.models.TaskExecutionPlan
import com.autoglm.android.core.models.UserIntent
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow

/**
 * 任务规划器，负责将用户意图转换为具体的任务执行计划
 */
class TaskPlanner(
    private val appKnowledgeBase: AppKnowledgeBase,
    private val llmService: LLMService
) {
    companion object {
        private const val TAG = "TaskPlanner"
        
        // 用于指导生成执行计划的系统提示词
        private const val SYSTEM_PROMPT_TEMPLATE = """
            你是一个专业的任务规划器，负责将用户意图转换为详细的执行步骤。
            
            你需要根据用户的意图和目标应用信息，生成一个结构化的执行计划JSON。执行计划应包含以下内容：
            
            1. 执行步骤列表（steps）：每个步骤包含以下字段：
               - id: 步骤唯一标识符（从1开始的数字）
               - description: 步骤描述
               - actionType: 动作类型，可以是以下之一：
                 * APP_LAUNCH: 启动应用
                 * CLICK: 点击元素
                 * SWIPE: 滑动屏幕
                 * ENTER_TEXT: 输入文本
                 * WAIT: 等待一段时间或特定条件
                 * SCREENSHOT: 截图
                 * CHECK_ELEMENT: 检查元素是否存在
                 * BACK: 返回上一页
                 * HOME: 返回主屏幕
                 * CUSTOM: 自定义操作
               - targetElement: 操作的目标元素（仅适用于部分动作类型）：
                 * 可以是元素ID
                 * 可以是元素描述（如"搜索框"、"确认按钮"等）
                 * 可以是坐标（如"200,300"）
               - params: 附加参数，JSON对象，根据动作类型不同而不同
               - successCriteria: 判断此步骤成功的条件描述
               - timeoutMs: 此步骤的超时时间（毫秒）
               - fallbackSteps: 当此步骤失败时的备选步骤ID列表
            
            2. 预估执行时长（estimatedDurationMs）：整个任务预计需要的时间（毫秒）
            
            3. 所需权限（requiredPermissions）：执行任务所需的权限列表
            
            4. 潜在失败点（potentialFailurePoints）：可能导致任务失败的环节列表
            
            以下是关于目标应用的重要信息，你可以用这些信息来生成更准确的执行计划：
            
            %s
            
            请确保输出的JSON格式正确无误，不要添加任何多余的解释或说明。
        """.trimIndent()
    }
    
    /**
     * 根据用户意图生成任务执行计划
     * 
     * @param intent 用户意图
     * @return 包含规划状态和执行计划的Flow
     */
    fun generatePlan(intent: UserIntent): Flow<TaskPlanningState> = flow {
        // 发送规划中状态
        emit(TaskPlanningState.Planning(intent))
        
        try {
            // 获取目标应用信息
            val appInfo = getAppInfo(intent.targetApp)
            if (appInfo == null) {
                emit(TaskPlanningState.Error("找不到应用信息: ${intent.targetApp}"))
                return@flow
            }
            
            // 构建用于生成执行计划的提示词
            val systemPrompt = SYSTEM_PROMPT_TEMPLATE.format(appInfoToString(appInfo))
            
            // 构建用户提示词（用户意图的JSON表示）
            val userPrompt = "用户意图: ${intent.toJson()}\n\n请基于此意图和应用知识生成详细的执行计划。"
            
            // 调用大模型生成执行计划
            val response = llmService.generateText(
                systemPrompt = systemPrompt,
                userPrompt = userPrompt,
                temperature = 0.2
            )
            
            // 解析响应中的执行计划
            val executionPlan = parseExecutionPlanFromResponse(response)
            
            // 发送规划成功状态
            emit(TaskPlanningState.Success(executionPlan))
        } catch (e: Exception) {
            Log.e(TAG, "Plan generation failed", e)
            // 发送规划失败状态
            emit(TaskPlanningState.Error("任务规划失败: ${e.message}"))
        }
    }
    
    /**
     * 获取应用信息
     */
    private suspend fun getAppInfo(appName: String): AppInfo? {
        return try {
            appKnowledgeBase.getAppInfoByName(appName)
        } catch (e: Exception) {
            Log.e(TAG, "Failed to get app info for $appName", e)
            null
        }
    }
    
    /**
     * 将应用信息转换为提示词中使用的字符串
     */
    private fun appInfoToString(appInfo: AppInfo): String {
        val sb = StringBuilder()
        sb.appendLine("应用名称: ${appInfo.appName}")
        sb.appendLine("包名: ${appInfo.packageName}")
        
        sb.appendLine("\n常见页面:")
        appInfo.commonScreens.forEach { screen ->
            sb.appendLine("- ${screen.screenName}: ${screen.description}")
        }
        
        sb.appendLine("\n常见UI元素:")
        appInfo.commonElements.forEach { element ->
            sb.appendLine("- ${element.elementId}: ${element.description}（屏幕: ${element.screenName}）")
        }
        
        sb.appendLine("\n操作知识:")
        appInfo.operationKnowledge.forEach { knowledge ->
            sb.appendLine("- ${knowledge.operation}: ${knowledge.description}")
        }
        
        return sb.toString()
    }
    
    /**
     * 从大模型响应中解析出执行计划
     */
    private fun parseExecutionPlanFromResponse(response: String): TaskExecutionPlan {
        try {
            // 尝试直接解析JSON
            return TaskExecutionPlan.fromJson(response)
        } catch (e: Exception) {
            Log.w(TAG, "Failed to parse direct JSON response, attempting to extract JSON from text", e)
            
            // 尝试从文本中提取JSON
            val jsonPattern = "\\{[\\s\\S]*\\}"
            val regex = Regex(jsonPattern)
            val matchResult = regex.find(response)
            
            if (matchResult != null) {
                val jsonString = matchResult.value
                return TaskExecutionPlan.fromJson(jsonString)
            } else {
                throw IllegalArgumentException("无法从响应中提取有效的JSON: $response")
            }
        }
    }
}

/**
 * 任务规划状态
 */
sealed class TaskPlanningState {
    /** 正在规划任务 */
    data class Planning(val intent: UserIntent) : TaskPlanningState()
    
    /** 任务规划成功 */
    data class Success(val plan: TaskExecutionPlan) : TaskPlanningState()
    
    /** 任务规划失败 */
    data class Error(val message: String) : TaskPlanningState()
} 